package com.sv.domain;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;

import com.sv.generic.SqlMapSpace;

@SqlMapSpace(name = "SQL_LIST", Class = PageInfo.class)
@Component
public class PageInfo {

    private int curPage = 0;

    private int perPage = 0;

    private String listSqlId;

    private int startRecord = 0;

    private int endRecord = 0;

    private int totalRecord = 0;

    private String orderByClause;

    private Map<String, Object> attrs;

    private List<Criteria> oredCriteria = new ArrayList<Criteria>();

    public int getCurPage() {
        return curPage;
    }

    public PageInfo setCurPage(int curPage) {
        this.curPage = curPage > 0 ? curPage : 0;
        intiRecordNum();
        return this;

    }

    public int getPerPage() {
        return perPage;
    }

    public PageInfo setPerPage(int perPage) {
        this.perPage = perPage < 0 ? 0 : perPage;
        intiRecordNum();
        return this;
    }

    public String getListSqlId() {
        return listSqlId;
    }

    public PageInfo setListSqlId(String listSqlId) {
        this.listSqlId = listSqlId;
        return this;
    }

    public int getStartRecord() {
        return startRecord;
    }

    public void setStartRecord(int startRecord) {
        this.startRecord = startRecord;
    }

    public int getEndRecord() {
        return endRecord;
    }

    public void setEndRecord(int endRecord) {
        this.endRecord = endRecord;
    }

    public int getTotalRecord() {
        return totalRecord;
    }

    public void setTotalRecord(int totalRecord) {
        this.totalRecord = totalRecord;
    }

    public String getOrderByClause() {
        return StringUtils.trimToNull(orderByClause);
    }

    public PageInfo setOrderByClause(String orderByClause) {
        this.orderByClause = StringUtils.trimToEmpty(orderByClause);

        return this;
    }

    public Map<String, Object> getAttrs() {
        return attrs;
    }

    public void setAttrs(Map<String, Object> attrs) {
        this.attrs = attrs;
    }

    /**
     * 设置查询记录的起始
     */
    private void intiRecordNum() {
        startRecord = (curPage - 1) * perPage > 0 ? (curPage - 1) * perPage : 0;

        endRecord = curPage * perPage;
    }

    public List<Criteria> getOredCriteria() {
        return oredCriteria;
    }

    public void setOredCriteria(List<Criteria> oredCriteria) {
        this.oredCriteria = oredCriteria;
    }

    public enum LikeModel {
        ALL, PRE, SUF
    };

    public enum NullModel {
        NULL, NOT_NULL
    }

    public Criteria creatCriteria() {
        Criteria criteria = new Criteria();
        if (oredCriteria.size() == 0) {
            oredCriteria.add(criteria);
        }
        return criteria;
    }

    public static class Criteria {
        protected List<String> criteriaWithoutValue;

        protected List<Map<String, Object>> criteriaWithSingleValue;

        protected List<Map<String, Object>> criteriaWithListValue;

        protected List<Map<String, Object>> criteriaWithBetweenValue;

        protected List<Map<String, Object>> criteriaWithLikeValue;

        protected Criteria() {
            super();
            criteriaWithoutValue = new ArrayList<String>();
            criteriaWithSingleValue = new ArrayList<Map<String, Object>>();
            criteriaWithListValue = new ArrayList<Map<String, Object>>();
            criteriaWithBetweenValue = new ArrayList<Map<String, Object>>();
            criteriaWithLikeValue = new ArrayList<Map<String, Object>>();
        }

        public boolean isValid() {
            return criteriaWithoutValue.size() > 0
                    || criteriaWithSingleValue.size() > 0
                    || criteriaWithListValue.size() > 0
                    || criteriaWithBetweenValue.size() > 0
                    || criteriaWithLikeValue.size() > 0;
        }

        public List<String> getCriteriaWithoutValue() {
            return criteriaWithoutValue;
        }

        public List<Map<String, Object>> getCriteriaWithSingleValue() {
            return criteriaWithSingleValue;
        }

        public List<Map<String, Object>> getCriteriaWithListValue() {
            return criteriaWithListValue;
        }

        public List<Map<String, Object>> getCriteriaWithBetweenValue() {
            return criteriaWithBetweenValue;
        }

        public Criteria addCriterion(String condition) {
            if (condition == null || StringUtils.isBlank(condition)) {
                throw new RuntimeException("condition cannot be null");
            }
            criteriaWithoutValue.add(condition);

            return this;
        }

        public Criteria addCriterion(String condition, Object value) {
            if (value == null) {
                throw new RuntimeException("Value cannot be null");
            }
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("condition", condition);
            map.put("value", value);
            criteriaWithSingleValue.add(map);

            return this;
        }

        public Criteria addInCriterion(String condition, List<Object> values) {
            if (values == null || values.size() == 0) {
                throw new RuntimeException("Value list cannot be null or empty");
            }
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("condition", condition);
            map.put("values", values);
            criteriaWithListValue.add(map);

            return this;
        }

        public Criteria addSelfCondition(String condition) {
            if (StringUtils.isBlank(condition)) {
                throw new RuntimeException("self condition can not be null!");
            }
            criteriaWithoutValue.add(condition);

            return this;
        }

        public Criteria addBetweenCriterion(String field, Object value1,
                Object value2) {
            if (value1 == null || value2 == null) {
                throw new RuntimeException(
                        "value1 and value2 can not be null !");
            }
            List<Object> list = new ArrayList<Object>();
            list.add(value1);
            list.add(value2);
            Map<String, Object> map = new HashMap<String, Object>();

            String condition = field + " between";


            map.put("condition", condition);
            map.put("values", list);
           
            criteriaWithBetweenValue.add(map);

            return this;
        }

        public Criteria addLikeCriterion(String filed, String value,
                LikeModel model) {

            filed = StringUtils.isBlank(filed) ? "" : StringUtils.trim(filed);

            if (StringUtils.isBlank(filed)) {
                throw new RuntimeException("filed cannot be null");
            }

            Map<String, Object> map = new HashMap<String, Object>();

            String condition = filed + " like";

            map.put("condition", condition);

            if (null != model) {
                switch (model) {
                    case ALL:
                        map.put("pre", "'%'");
                        map.put("suf", "'%'");
                        break;
                    case PRE:
                        map.put("pre", "'%'");
                        break;
                    case SUF:
                        map.put("suf", "'%'");
                }
            }

            map.put("value", value);

            criteriaWithLikeValue.add(map);
            return this;
        }
    }
}
